package service

import (
	"github.com/gin-gonic/gin"
	"github.com/mssola/user_agent"
	"gorm.io/gorm"
	"shop-common/library/variables"
	"shop-common/utils/contextArgs"
	"shop-common/utils/pagehelper"
	"shop-sys/model"
	"shop-sys/repository"
	"strconv"
	"strings"
	"time"
)

type SysLog struct {
	db         *gorm.DB
	repository repository.ISysLogRepository
}

func NewSysOtherService() *SysLog {
	return &SysLog{variables.GormDB(), repository.NewSysLogRepository()}
}

//todo 写日志 在serializer.** 方法下，使用chain的方式 并发写日志。
func (s *SysLog) Create(c *gin.Context, latencyTime time.Duration, terminal string) {
	if c.Request.RequestURI == "/" ||
		strings.Index(c.Request.RequestURI, "/sys/log/page") > -1 ||
		strings.Index(c.Request.RequestURI, "/static/") > -1 {
		return
	}
	sysHistory := model.SysLog{}
	// 请求方式
	reqMethod := c.Request.Method
	// 请求路由
	reqUri := c.Request.URL.Path

	// 状态码
	statusCode := c.Writer.Status()

	ua := user_agent.New(c.Request.UserAgent())
	browserName, browserVersion := ua.Browser()
	sysHistory.Browser = browserName + " " + browserVersion
	sysHistory.Os = ua.OS()
	sysHistory.Platform = ua.Platform()
	clientIP := c.ClientIP()
	sysHistory.ActionIp = clientIP
	// todo ip地址
	//sysOperLog.OperLocation = utils.GetLocation(clientIP).(string)
	sysHistory.Status = strconv.Itoa(statusCode)
	sysHistory.Terminal = terminal

	username, err := contextArgs.GetUserUserId(c)
	if err == nil {
		sysHistory.ActionName = username
	}

	id, err := contextArgs.GetUserInternalId(c)
	if err == nil {
		sysHistory.ActionId = id
	}

	sysHistory.RequestMethod = reqMethod
	sysHistory.ActionUrl = reqUri
	sysHistory.RawQuery = c.Request.URL.RawQuery
	if reqUri == "/app/login" {
		sysHistory.BusinessType = "10"
		sysHistory.Title = "用户登录"
	} else if strings.Contains(reqUri, "/app/logout") {
		sysHistory.Title = "用户登出"
		sysHistory.BusinessType = "11"
	} else if strings.Contains(reqUri, "/app/admin/base/captcha") {
		sysHistory.BusinessType = "12"
		sysHistory.Title = "验证码"
	} else {
		if reqMethod == "GET" {
			sysHistory.BusinessType = "1"
		} else if reqMethod == "POST" {
			sysHistory.BusinessType = "2"
		} else if reqMethod == "PUT" {
			sysHistory.BusinessType = "3"
		} else if reqMethod == "DELETE" {
			sysHistory.BusinessType = "4"
		}
	}
	payload, exist := c.Get("payload")
	if exist {
		sysHistory.ActionParam = payload.(string)
	}

	sysHistory.CreateBy = sysHistory.ActionName
	sysHistory.ActionTime = time.Now()
	sysHistory.LatencyTime = (latencyTime).String()
	if c.Err() == nil {
		sysHistory.Status = "1"
	} else {
		sysHistory.Status = "0"
	}

	_, err = s.repository.Create(s.db, &sysHistory)
	if err != nil {
		variables.Logger.Errorf(c, "record create log")
	}
}

func (s *SysLog) Page(paginator *pagehelper.Paginator) (*pagehelper.Record, error) {
	count, err := s.repository.Count(s.db, paginator.Params)
	if err != nil {
		return paginator.Record, err
	}

	if count == 0 {
		return paginator.Result(nil, count)
	}

	page, err := s.repository.FindPage(s.db, paginator.Params)
	if err != nil {
		return paginator.Record, err
	}
	return paginator.Result(page, count)
}
